'''
Created on 03.07.2013

@author: Indrek Jentson
'''
import evn.verbnet
from pyxb import *
from pyxb.namespace import *
from pyxb.binding import *
from pyxb.utils.domutils import *
from zipfile import *
from django.utils.translation import ugettext_lazy as _

class Importer(object):
    '''
    classdocs
    '''
    m_zip = None
    m_files = []
    m_current = -1
    m_doc = None
    m_status = ''
    m_message = ''
    m_ns = None
    m_dom = None

    def importFromZIPFile (self, p_file):
        self.m_zip = ZipFile(p_file, 'r')
        l_bad = self.m_zip.testzip()
        if l_bad == None:
            self.m_files = self.m_zip.namelist()
            self.m_current = -1
        else:
            self.m_status = _('Error')
            self.m_message = _('Corrupted file "%(name)" in %(loc)') % {'name':l_bad, 'loc':p_file.name}
        return

    def getNextFileFromZIP (self):
        self.m_current = self.m_current + 1
        if self.m_current < len(self.m_files):
            return self.m_zip.open(self.m_files[self.m_current], 'r')
        else:
            return None

    def hasZipFile(self):
        return self.m_zip != None

    def importFromXMLFile (self, filename):
        try:
            if type(filename) is str:
                xml = file(filename).read()
                self.m_doc = evn.verbnet.CreateFromDocument(xml, location_base=filename)
            else:  # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
                xml = filename.read()
                self.m_doc = evn.verbnet.CreateFromDocument(xml, location_base=filename.name)
            self.m_status = _('Ok')
            self.m_message = ''
            self.m_ns = evn.verbnet.Namespace
            self.m_ns.validateComponentModel(self.m_doc)
            self.m_dom = StringToDOM(xml)
        except pyxb.UnrecognizedContentError as e:
            self.m_status = _('Error')
            self.m_message = _('Unrecognized element "%(name)s" at %(loc)s') % {'name':e.content.expanded_name, 'loc':e.content.location}
        return

    def extractId (self, src=None):
        if src == None: src = self.m_doc
        i = ""
        if self.m_doc != None and self.m_status == _('Ok'):
            i = src.ID
        return i

    def extractMembers (self, src=None):
        if src == None: src = self.m_doc
        ms = []
        if self.m_doc != None and self.m_status == _('Ok'):
            members = src.MEMBERS.MEMBER
            for m in members:
                wnl = ""
                for w in m.wn:
                    if wnl != "": wnl = wnl + " "
                    wnl = wnl + w
                ms.append({'name':m.name, 'wn':wnl, 'grouping':m.grouping})
        return ms  # List of Member.json objects

    def extractSelectionRestrictions (self, src):
        se = []
        sr = []
        if src.logic == None: op = 'and'
        else: op = src.logic
        for r in src.SELRESTR:
            sr.append({'value':r.Value, 'type':r.type})
        for e in src.SELRESTRS:
            sr.append({'value':self.extractSelectionRestrictions(e), 'type':'exp'})
        se.append({'op':op, 'args':sr})
        return se

    def extractThemRoles (self, src=None):
        if src == None: src = self.m_doc
        tr = []
        if self.m_doc != None and self.m_status == _('Ok'):
            roles = src.THEMROLES.THEMROLE
            for r in roles:
                tr.append({'role':r.type, 'restrs':self.extractSelectionRestrictions(r.SELRESTRS)})
        return tr  # List of ThematicRole.json objects


    def locateSubClassFrameInDom (self, vncid, prim, src):
        lscs = LocateMatchingChildren(src, u"SUBCLASSES", self.m_ns)
        for lsc in lscs:
            lsvc = LocateMatchingChildren(lsc, u"VNSUBCLASS", self.m_ns)
            for lsv in lsvc:
                if NodeAttribute(lsv, u"ID") == vncid:
                    lfrs = LocateMatchingChildren(lsv, u"FRAMES", self.m_ns)
                    for lfr in lfrs:
                        lfs = LocateMatchingChildren(lfr, u"FRAME", self.m_ns)
                        for lf in lfs:
                            lds = LocateMatchingChildren(lf, u"DESCRIPTION", self.m_ns)
                            if NodeAttribute(lds[0], u"primary") == prim:
                                return lf
                res = self.locateSubClassFrameInDom (vncid, prim, lsv)
                if res != None:
                    return res

    def locateFrameInDom (self, vncid, prim):
        lvc = LocateMatchingChildren(self.m_dom, u"VNCLASS", self.m_ns)
        for lv in lvc:
            if NodeAttribute(lv, u"ID") == vncid:
                lfrs = LocateMatchingChildren(lv, u"FRAMES", self.m_ns)
                for lfr in lfrs:
                    lfs = LocateMatchingChildren(lfr, u"FRAME", self.m_ns)
                    for lf in lfs:
                        lds = LocateMatchingChildren(lf, u"DESCRIPTION", self.m_ns)
                        if NodeAttribute(lds[0], u"primary") == prim:
                            return lf
            res = self.locateSubClassFrameInDom (vncid, prim, lv)
            if res != None:
                return res

    def extractSyntaxRestrictionsInDom (self, restrictionsNode):
        se = []
        sr = []
        atr = NodeAttribute(restrictionsNode, u"logic")
        if atr == None: op = 'and'
        else: op = atr
        for r in restrictionsNode.childNodes:
            if r.nodeType == 1 and r.localName in [u"SYNRESTR"]:
                sr.append({'value':NodeAttribute(r, u"Value"), 'type':NodeAttribute(r, u"type")})
            if r.nodeType == 1 and r.localName in [u"SYNRESTRS"]:
                lv = self.extractSelectionRestrictionsInDom(r)
                if len(lv) > 0:
                    sr.append({'value':lv, 'type':'exp'})
        if len(sr) > 0:
            se.append({'op':op, 'args':sr})
        return se

    def extractSyntaxSelectionsInDom (self, restrictionsNode):
        se = []
        sr = []
        atr = NodeAttribute(restrictionsNode, u"logic")
        if atr == None: op = 'and'
        else: op = atr
        for r in restrictionsNode.childNodes:
            if r.nodeType == 1 and r.localName in [u"SELRESTR"]:
                sr.append({'value':NodeAttribute(r, u"Value"), 'type':NodeAttribute(r, u"type")})
            if r.nodeType == 1 and r.localName in [u"SELRESTRS"]:
                lv = self.extractSyntaxSelectionsInDom(r)
                if len(lv) > 0:
                    sr.append({'value':lv, 'type':'exp'})
        if len(sr) > 0:
            se.append({'op':op, 'args':sr})
        return se

    def extractSyntaxInDom (self, frameNode):
        sx = []
        i = 0
        lss = LocateMatchingChildren(frameNode, u"SYNTAX", self.m_ns)
        for ls in lss:
            for node in ls.childNodes:
                if node.nodeType == 1:
                    print '> ', node.localName
                    lv = None
                    if node.localName in [u"NP", u"PREP", u"LEX"]:
                        lv = NodeAttribute(node, u"value")
                        if lv != None:
                            print '>> ', lv
                    sr = []
                    ss = []
                    for rn in node.childNodes:
                        if rn.nodeType == 1 and rn.nodeName in [u"SYNRESTRS"]:
                            lr = self.extractSyntaxRestrictionsInDom(rn)
                            if len(lr) > 0:
                                sr = lr
                        if rn.nodeType == 1 and rn.nodeName in [u"SELRESTRS"]:
                            lr = self.extractSyntaxSelectionsInDom(rn)
                            if len(lr) > 0:
                                ss = lr
                    sx.append({'type':node.localName, 'value':lv, 'pos':i, 'restr':sr, 'select':ss})
                    i = i + 1
        print '# ', sx
        return {'phrases':sx, 'isOrdered':'Yes'}

    def extractArguments(self, argSet):
        args = []
        if self.m_doc != None and self.m_status == _('Ok'):
            al = argSet.ARG
            for a in al:
                args.append({'type':a.type, 'value':a.value_})
        return args

    def extractSemantics (self, frame):
        sm = []
        if self.m_doc != None and self.m_status == _('Ok'):
            preds = frame.SEMANTICS.PRED
            for p in preds:
                l_b = p.bool == '!'
                sm.append({'type':p.value_, 'bool':l_b, 'args':self.extractArguments(p.ARGS)})
                print p.value_, p.bool, l_b
        return {'predicates': sm}

    def extractFrames (self, vclid, src=None):
        if src == None: src = self.m_doc
        fr = []
        if self.m_doc != None and self.m_status == _('Ok'):
            frames = src.FRAMES.FRAME
            for f in frames:
                # print f.DESCRIPTION.descriptionNumber, f.DESCRIPTION.primary, f.DESCRIPTION.secondary, f.DESCRIPTION.xtag
                ex = ""
                for e in f.EXAMPLES.EXAMPLE:
                    for e2 in e.orderedContent():
                        if ex != "": ex = ex + " "
                        ex = ex + str(e2.value)
                        if not ex.endswith("."): ex = ex + "."
                # print '** ' + ex
                s = self.locateFrameInDom(vclid, f.DESCRIPTION.primary)
                sx = []
                if s != None:
                    sx.append(self.extractSyntaxInDom(s))
                else:
                    print 'ERROR: Cant locate frame |', vclid, '|', f.DESCRIPTION.primary, '|', src
                # print sx
                sem = []
                sem.append(self.extractSemantics(f))
                fr.append({'descriptionNumber':f.DESCRIPTION.descriptionNumber, 'primary':f.DESCRIPTION.primary, 'secondary':f.DESCRIPTION.secondary, 'xtag':f.DESCRIPTION.xtag, 'example':ex, 'syntax':sx, 'semantics':sem})
        return fr  # List of Frame.json objects

    def extractSubClasses (self, src=None):
        sc = []
        if src == None: src = self.m_doc
        if self.m_doc != None and self.m_status == _('Ok'):
            scs = src.SUBCLASSES.VNSUBCLASS
            for s in scs:
                l_id = self.extractId(s)
                l_mem = self.extractMembers(s)
                l_trs = self.extractThemRoles(s)
                l_frs = self.extractFrames(l_id, s)
                l_scl = self.extractSubClasses(s)
                sc.append({'name':l_id, 'members':l_mem, 'roles':l_trs, 'frames':l_frs, 'subclasses':l_scl})
        return sc  # List of VNModel.json objects

    def importFromXSDFile (self, filename):
        try:
            if type(filename) is str:
                xml = file(filename).read()
            else:  # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
                xml = filename.read()
            self.m_status = _('Ok')
            self.m_message = ''
            self.m_dom = StringToDOM(xml)
        except pyxb.UnrecognizedContentError as e:
            self.m_status = _('Error')
            self.m_message = _('Unrecognized element "%(name)s" at %(loc)s') % {'name':e.content.expanded_name, 'loc':e.content.location}
        return

    def extractTypes (self, typeId):
        prd = []
        if self.m_dom != None and self.m_status == _('Ok'):
            xss = LocateMatchingChildren(self.m_dom, u"schema")
            for xs in xss:
                sts = LocateMatchingChildren(xs, u"simpleType")
                for st in sts:
                    if NodeAttribute(st, u"name") == typeId:
                        rs = LocateMatchingChildren(st, u"restriction")
                        for r in rs:
                            ens = LocateMatchingChildren(r, u"enumeration")
                            for en in ens:
                                prd.append(NodeAttribute(en, u"value"))
        return prd


    def __init__(self):
        '''
        Constructor
        '''
        self.m_doc = None
        self.m_status = ''
        self.m_message = ''
